//
//  NSMagagedObject+ActiveRecord.swift
//  FearfulNotification
//
//  Created by 筱鹏 on 2017/9/27.
//  Copyright © 2017年 筱鹏. All rights reserved.
//

import UIKit
import CoreData

protocol ManagedObjectProtocol {
    
    //关联类型
    associatedtype WrapperType
    
    //关联属性: 实例属性
    var execute: WrapperType { get }
    
    //关联属性： 类 属性
    static var execute: WrapperType.Type { get }
    
}

extension ManagedObjectProtocol {
    var execute: ExtensionMethod<Self> {
        return ExtensionMethod(value: self)
    }
    
    static var execute: ExtensionMethod<Self>.Type {
        return ExtensionMethod.self
    }
}

extension NSManagedObject: ManagedObjectProtocol {}

//TODO: 增删改
extension ExtensionMethod where T: NSManagedObject {
    typealias ObjectClosure = (T) -> Void
    typealias ChangeObjectsClosure = (T, Int) -> Void
    
    
    //TODO: 实例对象 修改/删除
    /**
     * 修改对象
     * @param 修改使用 changeClosure 中的传出的 ManageObject
     */
    func change(_ finish: @escaping Store.FinishClosure = {_ in}, _ change: @escaping ObjectClosure) {
        Store.manager.performChange(objectId: wrappedValue.objectID, finish) { (obj) in
            let entity = obj as! T
            change(entity)
        }
    }
    
    /**
     * 删除自己
     */
    func delete(_ finish: @escaping Store.FinishClosure = {_ in}) {
        Store.manager.performDelete(objId: wrappedValue.objectID, finish)
    }
    
    //TODO: 插入
    /**
     *  插入一条新的NSManagedObject对象
     */
    static func insert(_ finish: @escaping Store.FinishClosure = {_ in}, _ completion: @escaping ObjectClosure){
        Store.manager.performInsert(T.entityName(), finish) { (obj) in
            let entity = obj as! T
            completion(entity)
        }
    }
    
    //TODO: 修改
    /**
     * 同时修改多条数据
     */
    static func change(_ objectIds: [NSManagedObjectID], _ finish: @escaping Store.FinishClosure = {_ in}, _ completion: @escaping ChangeObjectsClosure) {
        Store.manager.performChange(objectIds: objectIds, finish) { (obj, idx) in
            let entity = obj as! T
            completion(entity, idx)
        };
    }
    
    //TODO: 删除
    /**
     *  删除全部该实体数据
     */
    static func deleteAll(_ finish: @escaping Store.FinishClosure = {_ in}) {
        self.delete(entity: T.entityName(), "", finish)
    }
    
    /**
     *  根据谓词删除
     */
    static func delete(format predicate: String, _ finish: @escaping Store.FinishClosure = {_ in}) {
        self.delete(entity: T.entityName(), predicate, finish)
    }
    
    static func delete(entity name: String, _ predicate: String, _ finish: @escaping Store.FinishClosure = {_ in}) {
        Store.manager.performDelete(entityName: name, predicate, finish)
    }
    
    static func delete(objId: NSManagedObjectID, _ finish: @escaping Store.FinishClosure = {_ in}) {
        Store.manager.performDelete(objId: objId, finish)
    }
}

//TODO: 查询 查出的实体，只读不可写
extension ExtensionMethod where T: NSManagedObject {
    /**
     *  根据谓词查询
     */
    static func fetch(_ predicate: String) -> [T] {
        let request = T.defaultFetchRequest()
        if predicate.lengthOfBytes(using: .utf8) > 0 {
            let pred = NSPredicate(format: predicate)
            request.predicate = pred
        }
        return Store.manager.readFetch(request) as! [T]
    }
    
    /**
     *  根据谓词查询并排序
     */
    static func fetch(sortKey: String,_ ascending: Bool,_ predicate: String) -> [T] {
        let request = T.defaultFetchRequest()
        if  predicate.lengthOfBytes(using: .utf8) > 0 {
            let pred = NSPredicate(format: predicate)
            request.predicate = pred
        }
        if sortKey.lengthOfBytes(using: .utf8) > 0 {
            request.sortDescriptors = [NSSortDescriptor(key: sortKey, ascending: ascending)]
        }
        return Store.manager.readFetch(request) as! [T]
    }
    
    /**
     *  查询前n个数据并排序
     */
    static func fetch(limit:Int, _ sortKey: String, _ ascending: Bool) -> [T] {
        let request = T.defaultFetchRequest()
        if sortKey.lengthOfBytes(using: .utf8) > 0 {
            request.sortDescriptors = [NSSortDescriptor(key: sortKey, ascending: ascending)]
        }
        request.fetchLimit = limit
        return Store.manager.readFetch(request) as! [T]
    }
    
    /**
     *  查询所有数据并排序
     */
    static func fetchAll(_ sortKey: String, _ ascending: Bool) -> [T] {
        return self.fetch(sortKey: sortKey, ascending, "")
    }
    
    /**
     *  查询某一条件下消息个数
     */
    static func fetchCount(_ predicate: String) -> Int {
        let request = T.defaultFetchRequest()
        if predicate.lengthOfBytes(using: .utf8) > 0 {
            request.predicate = NSPredicate(format: predicate)
        }
        return Store.manager.readFetchCount(request)
    }
    
    /**
     *  获取NSFetchedResultsController
     */
    static func fetchResultsController(_ sortKey: String, _ ascending: Bool, _ predicate: String) -> NSFetchedResultsController<NSFetchRequestResult> {
        let request = T.defaultFetchRequest()
        if sortKey.lengthOfBytes(using: .utf8) > 0 {
            request.sortDescriptors = [NSSortDescriptor(key: sortKey, ascending: ascending)]
        }
        if predicate.lengthOfBytes(using: .utf8) > 0 {
            request.predicate = NSPredicate(format: predicate)
        }
        return Store.manager.readFetchResultController(request)
    }
}

extension NSManagedObject {
    /**
     *  NSManagedObject对应Entity的名称，默认与类名相同，可以在子类中重写
     */
    class func entityName() -> String {
        return String(describing: self.self)
    }
    
    /** 查询Request */
    class func defaultFetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
        return NSFetchRequest(entityName: self.entityName())
    }
}
